#ifndef TIMERS_H
#define TIMERS_H

// Purpose
//	To support both Atmega 128 and 1280 MCU's

typedef enum _eTimerStatus {
	eTmrOn,
	eTmrOff,
} _eTimerStatus ;

typedef enum _eTimerDividerScale {
	eTmrRTC,
	eTmrNormal
} _eTimerDividerScale; 

#define TIMER_CLK_STOP			0x00	///< Timer Stopped
#define TIMER_CLK_DIV1			0x01	///< Timer clocked at F_CPU
#define TIMER_CLK_DIV8			0x02	///< Timer clocked at F_CPU/8
#define TIMER_CLK_DIV64			0x03	///< Timer clocked at F_CPU/64
#define TIMER_CLK_DIV256		0x04	///< Timer clocked at F_CPU/256
#define TIMER_CLK_DIV1024		0x05	///< Timer clocked at F_CPU/1024
#define TIMER_CLK_T_FALL		0x06	///< Timer clocked at T falling edge
#define TIMER_CLK_T_RISE		0x07	///< Timer clocked at T rising edge
#define TIMER_PRESCALE_MASK		0x07	///< Timer Prescaler Bit-Mask

#define TIMERRTC_CLK_STOP		0x00	///< RTC Timer Stopped
#define TIMERRTC_CLK_DIV1		0x01	///< RTC Timer clocked at F_CPU
#define TIMERRTC_CLK_DIV8		0x02	///< RTC Timer clocked at F_CPU/8
#define TIMERRTC_CLK_DIV32		0x03	///< RTC Timer clocked at F_CPU/32
#define TIMERRTC_CLK_DIV64		0x04	///< RTC Timer clocked at F_CPU/64
#define TIMERRTC_CLK_DIV128		0x05	///< RTC Timer clocked at F_CPU/128
#define TIMERRTC_CLK_DIV256		0x06	///< RTC Timer clocked at F_CPU/256
#define TIMERRTC_CLK_DIV1024	0x07	///< RTC Timer clocked at F_CPU/1024
#define TIMERRTC_PRESCALE_MASK	0x07	///< RTC Timer Prescaler Bit-Mask

//Divider Hz Ranges for Maximum resolution for 16bit timers
#define DIV1024MAX(RES)			(F_CPU/(1024.0*RES))
#define DIV256MAX(RES)			(F_CPU/(256.0*RES))
#define DIV128MAX(RES)			(F_CPU/(128.0*RES))
#define DIV64MAX(RES)			(F_CPU/(64.0*RES))
#define DIV32MAX(RES)			(F_CPU/(32.0*RES))
#define DIV8MAX(RES)			(F_CPU/(8.0*RES))
#define DIV1MAX(RES)			(F_CPU/(RES))

// ELSE DIV1 Use
#define TIMER_NORMAL			0x00
#define TIMER_CTC				0x01
#define TIMER_PWM				0x02
#define TIMER_PWMFC				0x03

// All ADC Interrupt Definitions  
typedef enum _eTimerInterrupts {
#ifdef atmega1280
	eTimer0_CompareA,
	eTimer0_CompareB,
	eTimer0_Overflow,
	eTimer1_Capture,
	eTimer1_CompareA,
	eTimer1_CompareB,
	eTimer1_CompareC,
	eTimer1_Overflow,
	eTimer2_CompareA,
	eTimer2_CompareB,
	eTimer2_Overflow,
	eTimer3_Capture,
	eTimer3_CompareA,
	eTimer3_CompareB,
	eTimer3_CompareC,
	eTimer3_Overflow,
	eTimer4_Capture,
	eTimer4_CompareA,
	eTimer4_CompareB,
	eTimer4_CompareC,
	eTimer4_Overflow,
	eTimer5_Capture,
	eTimer5_CompareA,
	eTimer5_CompareB,
	eTimer5_CompareC,
	eTimer5_Overflow,
#else
	eTimer0_Compare,
	eTimer0_Overflow,
	eTimer1_Capture,
	eTimer1_CompareA,
	eTimer1_CompareB,
	eTimer1_CompareC,
	eTimer1_Overflow,
	eTimer2_Compare,
	eTimer2_Overflow,
	eTimer3_Capture,
	eTimer3_CompareA,
	eTimer3_CompareB,
	eTimer3_CompareC,
	eTimer3_Overflow,
#endif
	eTimerMax
} _eTimerInterrupts;

void	timers_initialise			(void);
// Initialise a timer
void	timer_initialise			(unsigned char num);
// Initialise a timer frequency
unsigned short	timer_initialise_mode		(unsigned char num, float freq, unsigned char mode);
unsigned short	timer_initialise_mode_exact	(unsigned char num, unsigned char div, unsigned short topVal, unsigned char mode);
// Attach a function to a timer overflow
void	timer_attach				(enum _eTimerInterrupts Interrupt, void (*userFunc)(void));
// Turn the PWM channel for timer on or off
void	timer_pwm_set				(unsigned char num, unsigned char chan, unsigned char state);
// Set the current value of the PWM output
void	timer_pwm_set_value			(unsigned char num, unsigned char chan, float nValue);
// Get the status of a timer
unsigned char	timer_status				(unsigned char num);

// Direct Timer Functions
void timer_1_pwm_A_set	(unsigned char state);
void timer_1_pwm_B_set	(unsigned char state);
void timer_1_pwm_C_set	(unsigned char state);
void timer_1_pwm_A_set_value (float nValue);
void timer_1_pwm_B_set_value (float nValue);
void timer_1_pwm_C_set_value (float nValue);
void timer_3_pwm_A_set	(unsigned char state);
void timer_3_pwm_B_set	(unsigned char state);
void timer_3_pwm_C_set	(unsigned char state);
void timer_3_pwm_A_set_value (float nValue);
void timer_3_pwm_B_set_value (float nValue);
void timer_3_pwm_C_set_value (float nValue);

#ifdef atmega128
void timer_0_pwm_set	(unsigned char state);
void timer_0_pwm_set_value (float nValue);
void timer_2_pwm_set	(unsigned char state);
void timer_2_pwm_set_value (float nValue);
#endif
#ifdef atmega1280
void timer_0_pwm_A_set	(unsigned char state);
void timer_0_pwm_B_set	(unsigned char state);
void timer_0_pwm_A_set_value (float nValue);
void timer_0_pwm_B_set_value (float nValue);
void timer_2_pwm_A_set	(unsigned char state);
void timer_2_pwm_B_set	(unsigned char state);
void timer_2_pwm_A_set_value (float nValue);
void timer_2_pwm_B_set_value (float nValue);
void timer_4_pwm_A_set	(unsigned char state);
void timer_4_pwm_B_set	(unsigned char state);
void timer_4_pwm_C_set	(unsigned char state);
void timer_4_pwm_A_set_value (float nValue);
void timer_4_pwm_B_set_value (float nValue);
void timer_4_pwm_C_set_value (float nValue);
void timer_5_pwm_A_set	(unsigned char state);
void timer_5_pwm_B_set	(unsigned char state);
void timer_5_pwm_C_set	(unsigned char state);
void timer_5_pwm_A_set_value (float nValue);
void timer_5_pwm_B_set_value (float nValue);
void timer_5_pwm_C_set_value (float nValue);
#endif

#endif
